package com.gitee.apanlh.util.net.http.handler;

import com.gitee.apanlh.exp.HttpException;
import com.gitee.apanlh.util.base.CollUtils;
import com.gitee.apanlh.util.net.http.HttpBody;
import com.gitee.apanlh.util.net.http.HttpClient;
import com.gitee.apanlh.util.net.http.HttpRequest;
import com.gitee.apanlh.util.net.http.HttpResponse;
import com.gitee.apanlh.util.net.http.handler.body.cast.HttpBodyCast;
import com.gitee.apanlh.util.net.http.handler.body.cast.HttpRequestBodyCast;
import com.gitee.apanlh.util.net.http.handler.body.cast.HttpRequestPreBodyCast;
import com.gitee.apanlh.util.reflection.ClassConvertUtils;
import com.gitee.apanlh.util.valid.ValidParam;

import java.util.List;

/**
 * 	HTTP拦截器链父类，用于拦截HTTP请求或响应
 * 	<br>责任链模式，按顺序执行所有的拦截器，依次对请求和响应进行处理
 *	
 * 	@author Pan
 */
public class HttpInterceptorChain implements InitializeInterceptors<HttpInterceptor> {
	
	/** 拦截器链 */
	private List<HttpInterceptor> interceptors;
	/** 当前执行拦截器链 */
	private HttpInterceptor interceptor;
	/** 拦截器链索引 */
	private int index;
	/** HttpBody转换器 */
	private HttpBodyCast bodyCast;
	 
	/**
	 * 	构造函数-默认初始化拦截链
	 * 	<br>有序集合
	 * 	
	 * 	@author Pan
	 */
	HttpInterceptorChain() {
		this(CollUtils.newArrayList());
	}
	
	/**
	 * 	构造函数-添加一个HTTP拦截器
	 * 	
	 * 	@author Pan
	 * 	@param 	interceptor  需要添加的拦截器
	 */
	HttpInterceptorChain(HttpInterceptor interceptor) {
		initializeInterceptors();
		addInterceptor(interceptor);
	}
	
	/**	
	 * 	构造函数-初始化链
	 * 	
	 * 	@author Pan
	 * 	@param 	interceptors	一个或多个链
	 */
	HttpInterceptorChain(List<HttpInterceptor> interceptors) {
		initializeInterceptors();
		CollUtils.addAll(this.interceptors, interceptors);
	}
	
	/**
	 * 	处理HTTP请求拦截器链，按照添加的顺序执行所有的HttpRequestInterceptor
	 * 	当有一个拦截器返回了null，则拦截器链停止执行，并将该HttpRequest返回。
	 * 
	 * 	@author Pan
	 * 	@param 	httpRequest 	HTTP请求对象
	 * 	@param 	httpClient		HTTP客户端
	 * 	@return HttpRequest		HTTP请求对象
	 * 	@throws HttpException 	处理异常，则抛出该异常
	 */
	public HttpRequest proceed(HttpRequest httpRequest, HttpClient httpClient) throws HttpException {
		HttpInterceptor next = next();
		if (next == null) {
			return httpRequest;
		}
		if (!(interceptor instanceof HttpRequestInterceptor) && !(interceptor instanceof HttpRequestPreInterceptor)) {
			throw new HttpException("please check interceptor type is not HttpRequestInterceptor or HttpRequestPreInterceptor");
		}
		if (interceptor instanceof HttpRequestPreInterceptor) {
			return ((HttpRequestPreInterceptor) interceptor).chain(httpRequest, httpClient, ClassConvertUtils.cast(getBodyCast(httpRequest)), this);
		}
		return ((HttpRequestInterceptor) interceptor).chain(httpRequest, httpClient, ClassConvertUtils.cast(getBodyCast(httpRequest)), this);
	}
	
	/**
	 * 	处理HTTP响应拦截器链，按照添加的顺序执行所有的HttpResponseInterceptor
	 * 	当有一个拦截器返回了null，则拦截器链停止执行，并将该HttpResponse返回。
	 * 
	 * 	@author Pan
	 * 	@param 	httpResponse  HTTP响应对象
	 * 	@return HttpResponse  HTTP响应对象
	 * 	@throws HttpException 处理异常，则抛出该异常
	 */
	public HttpResponse proceed(HttpResponse httpResponse) throws HttpException {
		HttpInterceptor next = next();
		if (next == null) {
			return httpResponse;
		}
		if (!(interceptor instanceof HttpRequestInterceptor)) {
			throw new HttpException("please check interceptor type is not HttpResponseInterceptor");
		}
		return ((HttpResponseInterceptor) interceptor).chain(httpResponse, this);
	}
	
	/**	
	 * 	添加拦截器
	 * 	
	 * 	@author Pan
	 * 	@param 	httpInterceptor	HTTP拦截器
	 * 	@return	HttpInterceptor
	 */
	public HttpInterceptor addInterceptor(HttpInterceptor httpInterceptor) {
		interceptors.add(httpInterceptor);
		return httpInterceptor;
	}
	
	/**	
	 * 	获取所有拦截器
	 * 	
	 * 	@author Pan
	 * 	@return	List
	 */
	public List<HttpInterceptor> getInterceptors() {
		return interceptors;
	}
	
	/**	
	 * 	获取下一个拦截器链
	 * 	<br>如果不存在拦截器链中为空，则返回null
	 * 	
	 * 	@author Pan
	 * 	@return	HttpInterceptor
	 */
	public HttpInterceptor next() {
		if (hasNext()) {
			this.interceptor = interceptors.get(index++);
			return interceptor;
		}
		return null;
	}
	
	/**	
	 * 	是否存在元素
	 * 	
	 * 	@author Pan
	 * 	@return	boolean
	 */
	public boolean hasNext() {
		return index < interceptors.size();
	}
	
	/**
	 * 	初始化加载创建拦截器列表
	 * 	
	 * 	@author Pan
	 */
	void initializeInterceptors() {
		if (this.interceptors == null) {
			this.interceptors = CollUtils.newArrayList();
		}
		loadExecute();
	}
	
	@Override
	public void loadExecute() throws HttpException {
		//	默认未实现
	}
	
	@Override
	public void load(HttpInterceptor t) throws HttpException {
		addInterceptor(t);
	}

	@Override
	public void load(List<HttpInterceptor> list) throws HttpException {
		interceptors.addAll(list);
	}
	
	/**	
	 * 	获取设置请求体/响应体转换器
	 * 	<br>不存在则初始化
	 * 	
	 * 	@author Pan
	 * 	@param 	httpRequest		HttpRequest对象
	 * 	@return	HttpBodyCast
	 */
	HttpBodyCast getBodyCast(HttpRequest httpRequest) {
		if (ValidParam.isNotNull(this.bodyCast)) {
			return this.bodyCast;
		}
		HttpBody httpBody = httpRequest.getBody();
		
		if (interceptor instanceof HttpRequestInterceptor) {
			this.bodyCast = new HttpRequestBodyCast(httpBody);
		}
		if (interceptor instanceof HttpRequestPreInterceptor) {
			this.bodyCast = new HttpRequestPreBodyCast(httpBody);
		}
		return this.bodyCast;
	}
}
